<template>
  <el-select
    v-bind="$attrs"
    v-model="model"
    :loading="loading"
    :remote-method="remoteMethod"
    :remote="$attrs.remote || true"
    :filterable="$attrs.filterable || true"
    :reserve-keyword="$attrs.reserveKeyword || true"
    :placeholder="$attrs.placeholder || '请选择所属地点'"
    @change="change"
    clearable
  >
    <el-option-group
      v-for="group in searchList"
      :key="group.label"
      :label="group.label"
    >
      <el-option
        v-for="item in group.options"
        :key="item.value"
        :label="item.label"
        :value="item"
      />
    </el-option-group>
  </el-select>
</template>
<script>
import request from '@/utils/request'

const searchApi = '/one-travel-api/position/searchPositionNmg'

const ENUM_ADDRESS_TYPE = [
  { label: '地区', type: 'dictAreaEntityList', typeId: '1' },
  { label: '景区', type: 'scenicEntityList', typeId: '3' },
  { label: '地区', type: 'city', typeId: '1' },
  { label: '区县', type: 'country', typeId: '2' },
  { label: '景点', type: 'scenic', typeId: '3' },
  { label: '场馆', type: 'venue', typeId: '4' }
]

const ENUM_FILTER_LEVEL = [
  { label: '一级过滤', value: 1 },
  { label: '二级过滤', value: 2 }
]

export default {
  props: {
    /* 绑定值
     * @params {String: label} 标签名
     * @params {String: value} 标签值
     * @params {String: type} 标签组类型
     */
    value: {
      // type: Object,
      default: _ => ({
        label: '',
        value: '',
        type: '',
        typeId: '',
      })
      // validator: obj => {
      //   return 'label' in obj && 'value' in obj && 'type' in obj
      // }
    },
    /* 需要过滤的地点层级
     * 1 - 一层返回的数据：['地区(注：地区下的地区、区县都作为地区数据处理)', '景区(注：景区下的景点、场馆都作为景区数据处理)']
     * 2 - 二层返回的数据：['地区', '区县', '景区', '场馆']
     */
    filterLevel: {
      type: Number,
      default: ENUM_FILTER_LEVEL[0].value
    },
    /* 需要过滤的地点类型 - 类型是Array，默认[]，表示获取所有地点类型
     * 1 - 地区
     * 2 - 区县
     * 3 - 景区
     * 4 - 场馆
     */

    filterType: {
      type: Array,
      default: _ => []
    },
    // 是否过滤掉没用空数据分组 - 为了ui好看点
    filterNull: {
      type: Boolean,
      default: false
    },
    // 过滤数据权限地区
    filterArea: {
      type: String,
      default: ''
    },
    label: '',
    valueData: '',
    type: '',
    typeId: ''
  },
  data () {
    return {
      loading: false,
      searchList: []
    }
  },
  computed: {
    // 跨组件双向绑定
    model: {
      get () {
        return this.value
      },
      set (newVal) {
        this.$emit('input', newVal)
      }
    }
  },
  watch: {
    // 解决回显问题 - 原因：/position/searchPositionNmg接口不是全量搜索：比如搜索内蒙古自治区赤峰市阿鲁科尔沁旗
    // 当key是'阿鲁科尔沁旗'时可以搜索到，但输入'内蒙古自治区赤峰市'是搜不到的，并且后台返回的地点名是组装后的全量
    // 地址'内蒙古自治区赤峰市阿鲁科尔沁旗'，就造成不能使用后台返回的地址名去通过remoteMethod方法拉取地址列表
    // 所属地点又有很多类型分类，野不能通过id/code单独的接口去搜索，回显比较麻烦

    // 满足一下两个条件时表示是数据回显
    // 1. 当双向绑定的value的值不存在于searchList列表项
    value: {
      handler (val, oldValue) {
        if (!val) return

        const getAllOption = data => {
          return [].concat(...data.map(item => item.options))
        }

        if (!getAllOption(this.searchList).includes(val)) {
          // 从value中取数据组合成searchList
          let labelType = ENUM_ADDRESS_TYPE.find(item => item.type === val.type)
          if (labelType) {
            this.searchList = [
              {
                label: labelType.label,
                options: [val]
              }
            ]
          }
        }
      },
      immediate: true
    },
    valueData: {
      handler (val, oldValue) {
        if (!val) return
        // 从value中取数据组合成searchList
        let labelType = ENUM_ADDRESS_TYPE.find(
          item => item.typeId === this.typeId
        )
        if (labelType) {
          let value = {
            label: this.label,
            value: this.valueData,
            type: labelType.type,
          }
          // 回显
          this.model = value
          this.searchList = [
            {
              label: labelType.label,
              options: [value]
            }
          ]
        }
      },
      immediate: true
    }
  },
  methods: {
    // 拦截双向绑定，向父级抛出
    change (event) {
      this.$emit('change', event ? event : { label: '', value: '', type: '' })
      this.$emit('update:label', event ? event.label : '')
      this.$emit('update:valueData', event ? event.value : '')
      this.$emit('update:type', event ? event.type : '')
      if (event?.type) {
        let typeItem = ENUM_ADDRESS_TYPE.filter(item => item.type == event.type)
        this.$emit(
          'update:typeId',
          typeItem.length > 0 ? typeItem[0].typeId : ''
        )
      } else {
        this.$emit('update:typeId', '')
      }
    },
    // 过滤 - 所属地点远程搜索建议
    remoteMethod (key) {
      if (!key || key === '') return
      this.loading = true
      this.search(key) // 远程搜索数据
        .then(res => this.filterData(res.data)) // 过滤数据
        .then(data => (this.searchList = data)) // 处理数据
        .finally(_ => (this.loading = false))
    },
    // 请求 - 搜索接口
    search (key) {
      return request({
        url: searchApi,
        method: 'POST',
        data: {
          key,
          levelFilterList: this.filterType
        }
      })
    },
    // 过滤 - 根据条件过滤数据, 过滤条件未作映射直接写死，后台反馈此接口不会改动
    async filterData (data) {
      // 如有权限地区，则过滤其他地区数据
      if (this.filterArea) {
        data.scenicEntityList = data.scenicEntityList.filter(
          c => c.cityCode == this.filterArea
        )
        data.dictAreaEntityList = data.dictAreaEntityList.filter(
          c => c.cityCode == this.filterArea
        )
      }
      let options = []

      // 只过滤一级数据
      if (this.filterLevel === ENUM_FILTER_LEVEL[0].value) {
        // 过滤地区
        let dictArea = data['dictAreaEntityList'].map(item => ({
          label: item.name,
          value: item.code,
          type: 'dictAreaEntityList',
          typeId: '1',
        }))
        options.push({ label: '地区', options: dictArea })

        // 过滤景区
        let scenic = data['scenicEntityList'].map(item => ({
          label: item.name,
          value: item.id,
          type: 'scenicEntityList',
          typeId: '3',
        }))
        options.push({ label: '景区', options: scenic })

        // 过滤两层数据
      } else if (this.filterLevel === ENUM_FILTER_LEVEL[1].value) {
        // 过滤地区 - 无countyCode表示地区
        let city = data['dictAreaEntityList']
          .filter(item => !item.countyCode)
          .map(item => ({
            label: item.name,
            value: item.code,
            type: 'city',
            typeId: '1',
          }))
        options.push({ label: '地区', options: city })

        // 过滤区县 - 有countyCode表示区县
        let country = data['dictAreaEntityList']
          .filter(item => item.countyCode)
          .map(item => ({
            label: item.name,
            value: item.code,
            type: 'country',
            typeId: '2',
          }))
        options.push({ label: '区县', options: country })

        // 过滤景区 - typeId = '01' 表示景区
        let scenic = data['scenicEntityList']
          .filter(item => item.typeId === '01')
          .map(item => ({
            label: item.name,
            value: item.id,
            type: 'scenic',
            typeId: '3',
          }))
        options.push({ label: '景点', options: scenic })

        // 过滤场馆 - typeId = '02' 表示场馆
        let venue = data['scenicEntityList']
          .filter(item => item.typeId === '02')
          .map(item => ({
            label: item.name,
            value: item.id,
            type: 'venue',
            typeId: '4',
          }))
        options.push({ label: '场馆', options: venue })
      }

      return this.filterNull
        ? options.filter(item => item.options.length > 0)
        : options
    }
  }
}
</script>
